package com.elephant.core.socket.socket2;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 2、客户端和服务端同时读和写
 *
 * 在socket通讯过程从InputStream输入流中读取数据时如果没有数据可读会一直阻塞，如果关闭流会返回-1。
 *          read方法在输入数据可用、检测到流末尾或者抛出异常前，此方法一直阻塞。意思就是说： 程序一直停在read()方法这里，等待数据。
 *     没有数据就不继续往下执行，至到得到数据
 * @author hai
 * @description
 * @date 10:57 2018/8/31
 */
public class Server {

    public static void main(String[] args) throws IOException {

        int port = 8888;
        ServerSocket server = new ServerSocket(port);
        Socket accept = server.accept();
        Reader reader = new InputStreamReader(accept.getInputStream());

        char[] chars = new char[64];
        int len;
        StringBuilder sb = new StringBuilder();
        while ((len = reader.read(chars)) != -1){
            sb.append(new String(chars,0,len));
        }

        System.out.println("From Client:" + sb);

        Writer writer = new OutputStreamWriter(accept.getOutputStream());
        writer.write("Hello Client");
        writer.flush();
        writer.close();

        reader.close();
        accept.close();
        server.close();
    }
}


/**
 * 在上述代码中首先我们从输入流中读取客户端发送过来的数据，接下来我们再往输出流里面写入数据给客户端，接下来关闭对应的资源文件。
 * 而实际上上述代码可能并不会按照我们预先设想的方式运行，
 * 因为从输入流中读取数据是一个阻塞式操作，在上述的while循环中当读到数据的时候就会执行循环体，否则就会阻塞，这样后面的写操作就永远都执行不了了。
 * 除非客户端对应的Socket关闭了阻塞才会停止，while循环也会跳出。
 * 针对这种可能永远无法执行下去的情况的解决方法是while循环需要在里面有条件的跳出来，纵观上述代码，在不断变化的也只有取到的长度len和读到的数据了，
 * len已经是不能用的了，唯一能用的就是读到的数据了。针对这种情况，通常我们都会约定一个结束标记，当客户端发送过来的数据包含某个结束标记时就说明当前的数据已经发送完毕了，
 * 这个时候我们就可以进行循环的跳出了。那么改进后的代码会是这个样子：
 */
